/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package jwu2.core;

import java.io.BufferedReader;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import jwu2.log.Logger;
import jwu2.net.ConnectionFactory;
import lombok.Cleanup;

/**
 *
 * @author Rolf
 */
public class Site implements Serializable {
    private String name;
    private String id;

    private String fetchURL = "";
    private String downloadURL = "";
    private String siteURL = "";
    private String addonDownloadInfoURL = "";

    private boolean multipleFetchUrl;
    private int beginFetchID;
    private boolean stopOnDate;
    private boolean createDownloadURL;
    private boolean twoStepDownloadURL;
    
    private Map<Site.Patterns, String> fetchPatterns;
    private boolean dateHasTime;
    private boolean dateAMPM;
    private boolean dateHasDayAndMonthSwapped;

    public void setAddonDownloadInfoURL(String url) {
        addonDownloadInfoURL = url;
    }
    
    public String getAddonDownloadInfoURL() {
        return addonDownloadInfoURL;
    }

    public boolean isTwoStepDownloadURL() {
        return twoStepDownloadURL;
    }
    
    public void setTwoStepDownloadURL(boolean b) {
        twoStepDownloadURL = b;
    }

    public boolean shouldCreateDownloadURL() {
        return createDownloadURL;
    }
    
    public void setCreateDownloadURL(boolean b) {
        createDownloadURL = b;
    }
    
    public boolean shouldStopOnDate() {
        return stopOnDate;
    }
    
    public void setStopOnDate(boolean b) {
        stopOnDate = b;
    }
    
    public String getDownloadURL() {
        return downloadURL;
    }

    public void setDownloadURL(String downloadURL) {
        this.downloadURL = downloadURL;
    }

    public String getSiteURL() {
        return siteURL;
    }

    public void setSiteURL(String siteURL) {
        this.siteURL = siteURL;
    }

    void setDateHasTime(boolean dateHasTime) {
        this.dateHasTime = dateHasTime;
    }

    void setDateIsAMPM(boolean dateAMPM) {
        this.dateAMPM = dateAMPM;
    }

    /**
     * @return the dateHasTime
     */
    public boolean isDateHasTime() {
        return dateHasTime;
    }

    /**
     * @return the dateAMPM
     */
    public boolean isDateAMPM() {
        return dateAMPM;
    }

    void setDateHasMonthAndDaySwapped(boolean dateHasDayAndMonthSwapped) {
        this.dateHasDayAndMonthSwapped = dateHasDayAndMonthSwapped;
    }

    /**
     * @return the dateHasDayAndMonthSwapped
     */
    public boolean isDateHasDayAndMonthSwapped() {
        return dateHasDayAndMonthSwapped;
    }

    public enum Patterns {
        NAME,
        AUTHOR,
        DESCRIPTION,
        ADDONSTART,
        ADDONEND,
        ENDMULTIPLEFETCH,
        DOWNLOADURL,
        ID,
        ENDOFPAGE,
        DATE,
        DOWNLOADPATTERN1,
        DOWNLOADPATTERN2,
    } 
    
    /**
     * Create a new Site
     * @param name the name of the site
     */
    public Site(String name) {
        this(name, name.replace(" ", "").toLowerCase().trim());
    }
    
    /**
     * Create a new Site
     * @param name the name of the site
     * @param id the id of the site
     */
    public Site(String name, String id) {
        this.name = name;
        this.id = id;
        
        fetchPatterns = new HashMap<Site.Patterns, String>();
        
        multipleFetchUrl = false;
        beginFetchID = 0;
    }

    public int getBeginFetchID() {
        return beginFetchID;
    }

    public void setBeginFetchID(int beginFetchID) {
        this.beginFetchID = beginFetchID;
    }
    
    public boolean isMultipleFetchUrl() {
        return multipleFetchUrl;
    }
    
    public void setMultipleFetchUrl(boolean b) {
        multipleFetchUrl = b;
    }
    
    public void addPattern(Site.Patterns name, String pattern) {
        fetchPatterns.put(name, pattern);
    }
    
    public Map<Site.Patterns, String> getFetchPatterns() {
        return fetchPatterns;
    }
    
    /**
     * Get the name of this site
     * @return the name of the site
     */
    public String getName() {
        return name;
    }

    /**
     * Get the id of this site
     * @return the id of the site
     */
    public String getId() {
        return id;
    }

    public void setFetchURL(String url) {
        fetchURL = url;
    }

    public String getFetchURL() {
        return fetchURL;
    }
    
    public String fetchDownloadURL(Addon addon) {
        String addonDownloadURL = null;
        
        Logger.logln("Fetching downloadURL for addon: "+addon+" from site: "+this);
        
        if( this.shouldCreateDownloadURL() ) {
            Map<Site.Patterns, String> patterns = this.getFetchPatterns();

            String url = this.getAddonDownloadInfoURL();
            
            System.out.println(""+url);

            url = url.replace("%addonid%", addon.getId());

            System.out.println(""+url);

            try {
                @Cleanup BufferedReader reader = ConnectionFactory.getReaderFromURLNoCache(url);

                Pattern addonDownloadURLPattern = Pattern.compile(patterns.get(Site.Patterns.DOWNLOADPATTERN1));

                Matcher m;
                String line;

                line = reader.readLine();

                while(line != null) {
                    line = line.trim();

                    //Fix up some html encoding
                    line = line.replaceAll("&#039;", "'");
                    line = line.replaceAll("&amp;", "&");

                    //System.out.println(line);

                    //AddonStart (New addon)
                    m = addonDownloadURLPattern.matcher(line);
                    if( m.matches() ) {
                        addonDownloadURL = m.group(1);

                        break;
                    }

                    line = reader.readLine();
                }
            }
            catch(Exception e) {
                Logger.logln("Exception retrieveing addon downloadurl for "+addon+": "+e);
            }

            if(addonDownloadURL != null) {
                if( this.isTwoStepDownloadURL() ) {

                    System.out.println(""+this.getSiteURL()+"/"+addonDownloadURL);

                    try {
                        @Cleanup BufferedReader reader = ConnectionFactory.getReaderFromURLNoCache(this.getSiteURL()+"/"+addonDownloadURL);

                        Pattern addonDownloadURLPattern = Pattern.compile(patterns.get(Site.Patterns.DOWNLOADPATTERN2));

                        Matcher m;
                        String line;

                        line = reader.readLine();

                        while(line != null) {
                            line = line.trim();

                            //Fix up some html encoding
                            line = line.replaceAll("&#039;", "'");
                            line = line.replaceAll("&amp;", "&");

                            //System.out.println(line);

                            //AddonStart (New addon)
                            m = addonDownloadURLPattern.matcher(line);
                            if( m.matches() ) {
                                addonDownloadURL = m.group(1);

                                break;
                            }

                            line = reader.readLine();
                        }
                    }
                    catch(Exception e) {
                        Logger.logln("Exception retrieveing addon downloadurl for "+addon+": "+e);
                    }
                }
            }
        }
        else {
            addonDownloadURL = addon.getDownloadUrl();
        }
        
        String result = this.getDownloadURL();
        
        result = result.replace("%url%", addonDownloadURL);
        result = result.replace("%siteurl%", this.getSiteURL());
        
        return result;
    }

    @Override
    public boolean equals(Object o) {
        if( o instanceof Site ) {
            Site s = (Site) o;
            
            return s.getName().equals(this.getName()) && s.getId().equals(this.getId());
        }
        
        return false;
    }

    @Override
    public int hashCode() {
        int hash = 7;
        hash = 17 * hash + (this.name != null ? this.name.hashCode() : 0);
        hash = 17 * hash + (this.id != null ? this.id.hashCode() : 0);
        return hash;
    }
    
    @Override
    public String toString() {
        return name;
    }
}
